package com.hongyi.common.redis.config;

import com.hongyi.common.framework.constant.CacheConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

/**
 * Redis配置类
 *
 * @author DingHao
 */
@Slf4j
@EnableCaching
@Configuration
public class RedisConfig {

    public RedisConfig() {
        log.info("加载Redis配置");
    }

    /**
     * 自定义redis序列化格式
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {//speingboot2.7版本会爆红，但不影响使用
        //创建操作redis的Spring Data Redis类
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        //设置连接工厂，这是与Redis服务器建立连接所必需的
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //自定义的序列化器，基于Fastjson库，用于将对象转换成JSON格式的数据存储到Redis中，或者从Redis中读取JSON格式的数据并转换回对象
        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);

        //redis的key会被序列化成字符串格式
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置String类型 value的序列化方式,value会被序列化成JSON格式
        redisTemplate.setValueSerializer(serializer);

        //hash类型field会被序列化成字符串格式
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //hash value会被序列化成JSON格式
        redisTemplate.setHashValueSerializer(serializer);

        //此方法是为了确保所有必需的属性都已经设置完毕
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /**
     * 自定义cache管理
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        //自定义的序列化器
        FastJson2JsonRedisSerializer<Object> serializer = new FastJson2JsonRedisSerializer<>(Object.class);
        //自定义RedisCacheConfiguration
        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(1)) // 设置缓存过期时间为1小时
                .computePrefixWith(name -> CacheConstants.GLOBAL_REDIS_KEY + name + ":")//设置缓存前缀,解决双::的问题
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer));//设置序列化器
        return RedisCacheManager.builder(redisConnectionFactory)//使用 RedisCacheManager 的构建器创建一个新的 RedisCacheManager 实例
                .cacheDefaults(cacheConfiguration)//设置默认的缓存配置
                .build();
    }

    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }

}
